package com.ecarx.vhaltests.hy11.testcases.climate;

import static com.ecarx.xui.adaptapi.car.hvac.IFragrance.AIR_FRAGRANCE_SLOT_1;
import static com.ecarx.xui.adaptapi.car.hvac.IFragrance.AIR_FRAGRANCE_SLOT_2;
import static com.ecarx.xui.adaptapi.car.hvac.IFragrance.AIR_FRAGRANCE_SLOT_3;
import static com.ecarx.xui.adaptapi.car.hvac.IFragrance.HVAC_FUNC_AIR_FRAGRANCE_SLOT;
import static com.ecarx.xui.adaptapi.car.hvac.IFragrance.HVAC_FUNC_AIR_FRAGRANCE_TYPE_ID;
import static org.junit.Assert.assertEquals;

import android.car.VehicleAreaType;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.CarPropertyManager;
import android.util.Log;

import androidx.test.platform.app.InstrumentationRegistry;

import com.ecarx.vhaltests.IpcpClient;
import com.ecarx.vhaltests.R;
import com.ecarx.vhaltests.VehicleConstants;
import com.ecarx.vhaltests.VhalUnitTestBase;
import com.ecarx.xui.adaptapi.car.IWrapper;

import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class HvacFuncAirFragranceSlotTest extends VhalUnitTestBase {
    private static IWrapper.IPropertyId propertyId;
    protected static IWrapper wrapper;
    private static IpcpClient ipcpClient = new IpcpClient();
    private static final int AREA_ID = VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL;
    private static int SLOT_1;
    private static int SLOT_2;
    private static int SLOT_3;

    private static int cbkPropValue;
    private static int cbkPropStatus;
    final static Object lock = new Object();

    @BeforeClass
    public static void testInit() {
        wrapper = com.ecarx.xui.adaptapi.car.Car.createWrapper(InstrumentationRegistry.getInstrumentation().getTargetContext());
        propertyId = wrapper.getWrappedPropertyId(IWrapper.WrappedIdType.ID_TYPE_FUNCTION, HVAC_FUNC_AIR_FRAGRANCE_SLOT);
        SLOT_1 = propertyId.getPropertyValue(AIR_FRAGRANCE_SLOT_1);
        SLOT_2 = propertyId.getPropertyValue(AIR_FRAGRANCE_SLOT_2);
        SLOT_3 = propertyId.getPropertyValue(AIR_FRAGRANCE_SLOT_3);
        setConfig();
    }

    public boolean availability(){
        return mCarPropertyMgr.isPropertyAvailable(propertyId.getPropertyId(), AREA_ID);
    }

    public static void setConfig(){
        int ccSvcId = 135;
        int[] ccOperIds = {200};
        boolean ccSet = ipcpClient.setConfig(ccSvcId, ccOperIds);
        assertEquals(true, ccSet);

        int cemSvcId = 37;
        int[] cemOperId = {999};
        boolean cemResult = ipcpClient.setConfig(cemSvcId, cemOperId);
        assertEquals(true, cemResult);
        delay();
    }

    public void setCarConfig(boolean isAvail){
        int ccSvcId = 135;
        int ccOperIds = 200;
        int[] configs = {505};
        int[] values = {isAvail? 2:1};
        boolean ccResult = ipcpClient.setCarconfigSignal(ccSvcId, ccOperIds, configs, values);
        delay();
        assertEquals(true, ccResult);
        Log.d("vli", "setCarConfig pass");
    }

    public void setCem(boolean isActive){
        int cemSvcId = 37;
        int cemOperId = 999;
        String[] cems = {"vehModMngtGlbSafe1UsgModSts","vehModMngtGlbSafe1CarModSts1"};
        int[] cemValues = {isActive? VehicleConstants.USG_MODE_CONVENIENCE:VehicleConstants.USG_MODE_ABANDON,
                VehicleConstants.CAR_MODE_DYNO};
        boolean cemUsgResult = ipcpClient.setCEMSignal(cemSvcId, cemOperId, cems, cemValues);
        delay();
        assertEquals(true, cemUsgResult);
        Log.d("vli", "setCem pass");
    }

    public void mockAirFragChRunngSts(int AirFragCh1RunngSts, int AirFragCh2RunngSts, int AirFragCh3RunngSts){
        int cemSvcId = 37;
        int cemOperId = 999;
        String[] cems = {"vehModMngtGlbSafe1UsgModSts","vehModMngtGlbSafe1CarModSts1","airFragCh1RunngSts","airFragCh2RunngSts","airFragCh3RunngSts"};
        int[] cemValues = {VehicleConstants.USG_MODE_CONVENIENCE,
                VehicleConstants.CAR_MODE_DYNO, AirFragCh1RunngSts, AirFragCh2RunngSts, AirFragCh3RunngSts};
        boolean cemUsgResult = ipcpClient.setCEMSignal(cemSvcId, cemOperId, cems, cemValues);
        assertEquals(true,cemUsgResult);
        delay();
    }

    public void lockWait() {
        try {
            synchronized (lock) {
                lock.wait(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test_001AirFragranceSlotActive(){
        setCarConfig(true);
        setCem(true);
        int propStatus = mCarPropertyMgr.getProperty(propertyId.getPropertyId(), AREA_ID).getStatus();
        assertEquals(0, propStatus);
    }

    @Test
    public void test_002AirFragranceSlotNotActive(){
        setCarConfig(true);
        setCem(false);
        int propStatus = mCarPropertyMgr.getProperty(propertyId.getPropertyId(),AREA_ID).getStatus();
        assertEquals(1, propStatus);
    }

    @Test
    public void test_003AirFragranceSlotNotAvail(){
        setCarConfig(false);
        assertEquals(false, availability());
    }

    @Test
    public void test_004SetAirFragranceSlot1(){
        setCarConfig(true);
        setCem(true);
        mCarPropertyMgr.setIntProperty(propertyId.getPropertyId(), AREA_ID, SLOT_1);
        mockAirFragChRunngSts(1,0,0);
        delay(3000);
        int res = mCarPropertyMgr.getIntProperty(propertyId.getPropertyId(), AREA_ID);
        assertEquals(SLOT_1, res);
    }

    @Test
    public void test_005SetAirFragranceSlot2(){
        setCarConfig(false);
        setCarConfig(true);
        setCem(true);
        mCarPropertyMgr.setIntProperty(propertyId.getPropertyId(), AREA_ID, SLOT_2);
        mockAirFragChRunngSts(0,1,0);
        delay(3000);
        int res = mCarPropertyMgr.getIntProperty(propertyId.getPropertyId(), AREA_ID);
        assertEquals(SLOT_2, res);
    }

    @Test
    public void test_006SetAirFragranceSlot3(){
        setCarConfig(false);
        setCarConfig(true);
        setCem(true);
        mCarPropertyMgr.setIntProperty(propertyId.getPropertyId(), AREA_ID, SLOT_3);
        mockAirFragChRunngSts(0,0,1);
        delay(3000);
        int res = mCarPropertyMgr.getIntProperty(propertyId.getPropertyId(), AREA_ID);
        assertEquals(SLOT_3, res);
    }

    @Test
    public void test_007AirFragranceSlotCallback(){
        CarPropertyManager.CarPropertyEventCallback carPropertyEventCallback = new CarPropertyManager.CarPropertyEventCallback() {
            @Override
            public void onChangeEvent(CarPropertyValue carPropertyValue) {
                cbkPropValue = (int)carPropertyValue.getValue();
                cbkPropStatus = carPropertyValue.getStatus();
            }

            @Override
            public void onErrorEvent(int i, int i1) {

            }
        };

        mCarPropertyMgr.registerCallback(carPropertyEventCallback, propertyId.getPropertyId(), CarPropertyManager.SENSOR_RATE_ONCHANGE);
        CarPropertyValue<Integer> carProp = mCarPropertyMgr.getProperty(Integer.class, propertyId.getPropertyId(), AREA_ID);
        int oldPropStatus = carProp.getStatus();
        if(oldPropStatus == 0){
            //set notAvail
            setCarConfig(false);
            assertEquals(false, availability());
        }else{
            //set Active
            setCarConfig(true);
            setCem(true);
            lockWait();
            assertEquals(0, cbkPropStatus);
            mCarPropertyMgr.setIntProperty(propertyId.getPropertyId(), AREA_ID, SLOT_3);
            mockAirFragChRunngSts(0,0,1);
            lockWait();
            int res = mCarPropertyMgr.getIntProperty(propertyId.getPropertyId(), AREA_ID);
            assertEquals(SLOT_3, res);
        }
        mCarPropertyMgr.unregisterCallback(carPropertyEventCallback);
    }

    @Test
    public void test_008McuAllOffWithNoOper(){
        setCarConfig(false);
        setCarConfig(true);
        setCem(true);
        mCarPropertyMgr.setIntProperty(propertyId.getPropertyId(), AREA_ID, SLOT_1);
        mockAirFragChRunngSts(1,0,0);
        lockWait();
        int lastRes = mCarPropertyMgr.getIntProperty(propertyId.getPropertyId(), AREA_ID);
        assertEquals(SLOT_1, lastRes);
        lockWait();
        mockAirFragChRunngSts(0,0,0);
        int Res = mCarPropertyMgr.getIntProperty(propertyId.getPropertyId(),AREA_ID);
        assertEquals(SLOT_1, Res);
    }

    @Test
    public void test_009updateReqByMcuSignal(){
        setCarConfig(false);
        setCarConfig(true);
        setCem(true);
        mockAirFragChRunngSts(0,1,0);
        lockWait();
        int res = mCarPropertyMgr.getIntProperty(propertyId.getPropertyId(), AREA_ID);
        assertEquals(SLOT_2, res);
    }
}